package com.bamboo.core.util;

import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.OSFileStore;
import oshi.util.FormatUtil;
import oshi.util.Util;

import java.util.List;

public class SystemUtil {
    private static final SystemInfo SYSTEM_INFO = new SystemInfo();
    private static final HardwareAbstractionLayer HARDWARE = SYSTEM_INFO.getHardware();
    private static final long SLEEP_INTERVAL = 1000L;

    public static class ServerInfo {
        private CpuInfo cpu;
        private MemoryInfo memory;
        private DiskInfo disk;

        public ServerInfo(CpuInfo cpu, MemoryInfo memory, DiskInfo disk) {
            this.cpu = cpu;
            this.memory = memory;
            this.disk = disk;
        }
    }
    // 内部类定义
    public static class CpuInfo {
        private double usage;  // CPU使用率
        private int logicalCores; // 逻辑核心数

    }

    public static class MemoryInfo {
        private String total;   // 总内存(GB)
        private String used;    // 已用内存(GB)
        private double usage;   // 内存使用率

    }

    public static class DiskInfo {
        private String total;
        private String used;
        private double usage;
    }

    public static ServerInfo getServerInfo() {
        return new ServerInfo(getCpuUsage(), getMemoryUsage(), getDiskUsage());
    }

    private static CpuInfo getCpuUsage() {
        CentralProcessor processor = HARDWARE.getProcessor();
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        Util.sleep(SLEEP_INTERVAL);

        CpuInfo cpu = new CpuInfo();
        cpu.logicalCores = processor.getLogicalProcessorCount();

        long[] ticks = processor.getSystemCpuLoadTicks();
        double total = 0.0;
        for (int i = 0; i < ticks.length; i++) {
            total += ticks[i] - prevTicks[i];
        }
        if (total > 0) {
            cpu.usage = Math.round(10000.0 * (total - (ticks[CentralProcessor.TickType.IDLE.getIndex()]
                    - prevTicks[CentralProcessor.TickType.IDLE.getIndex()])) / total) / 100.0;
        }
        return cpu;
    }

    private static MemoryInfo getMemoryUsage() {
        GlobalMemory memory = HARDWARE.getMemory();
        MemoryInfo mem = new MemoryInfo();

        long totalBytes = memory.getTotal();
        long availableBytes = memory.getAvailable();

        mem.total = FormatUtil.formatBytes(totalBytes);
        mem.used = FormatUtil.formatBytes(totalBytes - availableBytes);
        mem.usage = Math.round(10000.0 * (totalBytes - availableBytes) / totalBytes) / 100.0;
        return mem;
    }

    private static DiskInfo getDiskUsage() {
        // 获取操作系统文件存储信息
        List<OSFileStore> fileStores = SYSTEM_INFO.getOperatingSystem().getFileSystem().getFileStores();

        long allDiskTotalBytes = 0L;
        long allDiskUsedBytes = 0L;
        for (OSFileStore fs : fileStores) {
            // 过滤逻辑分区和虚拟磁盘（仅保留物理磁盘）
            if (isPhysicalDisk(fs)) {
                long totalBytes = fs.getTotalSpace();
                long freeBytes = fs.getFreeSpace();
                long usedBytes = totalBytes - freeBytes;

                // 处理异常值（确保不出现负值）
                if (totalBytes <= 0 || freeBytes < 0) {
                    continue; // 跳过无效数据
                }
                allDiskTotalBytes += totalBytes;
                allDiskUsedBytes += usedBytes;
            }
        }
        DiskInfo diskInfo = new DiskInfo();
        diskInfo.total = FormatUtil.formatBytes(allDiskTotalBytes);
        diskInfo.used = FormatUtil.formatBytes(allDiskUsedBytes);
        diskInfo.usage = Math.round(10000.0 * allDiskUsedBytes / allDiskTotalBytes) / 100.0;
        return diskInfo;
    }

    // 判断是否为物理磁盘（过滤临时文件系统）
    private static boolean isPhysicalDisk(OSFileStore fs) {
        return !fs.getType().equalsIgnoreCase("tmpfs") &&
                !fs.getMount().startsWith("/dev") &&
                fs.getTotalSpace() > 0;
    }
}